//
//  IMJSONUtils.m
//  DualMediationSDK
//
//  Created by YeJary on 2025/6/23.
//

#import "IMJSONUtils.h"
#import "../Logger/IMLogUtils.h"

@implementation IMJSONUtils

#pragma mark - JSON Conversion

+ (NSString *)jsonStringFromObject:(id)object {
    return [self jsonStringFromObject:object prettyPrint:NO];
}

+ (NSString *)jsonStringFromObject:(id)object prettyPrint:(BOOL)prettyPrint {
    if (!object) return nil;
    
    NSError *error;
    NSJSONWritingOptions options = prettyPrint ? NSJSONWritingPrettyPrinted : 0;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:object options:options error:&error];
    
    if (error) {
        [IMLogUtils error:IMLogTagError format:@"JSON serialization error: %@", error.localizedDescription];
        return nil;
    }
    
    return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}

+ (id)objectFromJSONString:(NSString *)jsonString {
    if (!jsonString || jsonString.length == 0) return nil;
    
    NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
    return [self objectFromJSONData:jsonData];
}

+ (NSData *)jsonDataFromObject:(id)object {
    return [self jsonDataFromObject:object prettyPrint:NO];
}

+ (NSData *)jsonDataFromObject:(id)object prettyPrint:(BOOL)prettyPrint {
    if (!object) return nil;
    
    NSError *error;
    NSJSONWritingOptions options = prettyPrint ? NSJSONWritingPrettyPrinted : 0;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:object options:options error:&error];
    
    if (error) {
        [IMLogUtils error:IMLogTagError format:@"JSON serialization error: %@", error.localizedDescription];
        return nil;
    }
    
    return jsonData;
}

+ (id)objectFromJSONData:(NSData *)jsonData {
    if (!jsonData || jsonData.length == 0) return nil;
    
    NSError *error;
    id object = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
    
    if (error) {
        [IMLogUtils error:IMLogTagError format:@"JSON deserialization error: %@", error.localizedDescription];
        return nil;
    }
    
    return object;
}

#pragma mark - JSON Validation

+ (BOOL)isValidJSONString:(NSString *)jsonString {
    if (!jsonString || jsonString.length == 0) return NO;
    
    NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
    return [self isValidJSONData:jsonData];
}

+ (BOOL)isValidJSONData:(NSData *)jsonData {
    if (!jsonData || jsonData.length == 0) return NO;
    
    NSError *error;
    [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
    return error == nil;
}

+ (BOOL)isValidJSONObject:(id)object {
    if (!object) return NO;
    return [NSJSONSerialization isValidJSONObject:object];
}

#pragma mark - JSON Formatting

+ (NSString *)prettyJSONString:(NSString *)jsonString {
    id object = [self objectFromJSONString:jsonString];
    return [self jsonStringFromObject:object prettyPrint:YES];
}

+ (NSString *)minifyJSONString:(NSString *)jsonString {
    id object = [self objectFromJSONString:jsonString];
    return [self jsonStringFromObject:object prettyPrint:NO];
}

#pragma mark - Safe Dictionary Access

+ (NSString *)safeStringFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key {
    return [self safeStringFromDictionary:dictionary forKey:key defaultValue:nil];
}

+ (NSString *)safeStringFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key defaultValue:(NSString *)defaultValue {
    if (!dictionary || !key) return defaultValue;
    
    id value = dictionary[key];
    if ([value isKindOfClass:[NSString class]]) {
        return value;
    } else if ([value isKindOfClass:[NSNumber class]]) {
        return [value stringValue];
    } else if ([value isKindOfClass:[NSNull class]] || !value) {
        return defaultValue;
    }
    
    // 尝试转换为字符串
    return [NSString stringWithFormat:@"%@", value] ?: defaultValue;
}

+ (NSNumber *)safeNumberFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key {
    return [self safeNumberFromDictionary:dictionary forKey:key defaultValue:nil];
}

+ (NSNumber *)safeNumberFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key defaultValue:(NSNumber *)defaultValue {
    if (!dictionary || !key) return defaultValue;
    
    id value = dictionary[key];
    if ([value isKindOfClass:[NSNumber class]]) {
        return value;
    } else if ([value isKindOfClass:[NSString class]]) {
        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
        formatter.numberStyle = NSNumberFormatterDecimalStyle;
        return [formatter numberFromString:value] ?: defaultValue;
    } else if ([value isKindOfClass:[NSNull class]] || !value) {
        return defaultValue;
    }
    
    return defaultValue;
}

+ (NSArray *)safeArrayFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key {
    return [self safeArrayFromDictionary:dictionary forKey:key defaultValue:nil];
}

+ (NSArray *)safeArrayFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key defaultValue:(NSArray *)defaultValue {
    if (!dictionary || !key) return defaultValue;
    
    id value = dictionary[key];
    if ([value isKindOfClass:[NSArray class]]) {
        return value;
    }
    
    return defaultValue;
}

+ (NSDictionary *)safeDictionaryFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key {
    return [self safeDictionaryFromDictionary:dictionary forKey:key defaultValue:nil];
}

+ (NSDictionary *)safeDictionaryFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key defaultValue:(NSDictionary *)defaultValue {
    if (!dictionary || !key) return defaultValue;
    
    id value = dictionary[key];
    if ([value isKindOfClass:[NSDictionary class]]) {
        return value;
    }
    
    return defaultValue;
}

+ (BOOL)safeBoolFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key {
    return [self safeBoolFromDictionary:dictionary forKey:key defaultValue:NO];
}

+ (BOOL)safeBoolFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key defaultValue:(BOOL)defaultValue {
    if (!dictionary || !key) return defaultValue;
    
    id value = dictionary[key];
    if ([value isKindOfClass:[NSNumber class]]) {
        return [value boolValue];
    } else if ([value isKindOfClass:[NSString class]]) {
        NSString *stringValue = [(NSString *)value lowercaseString];
        return [stringValue isEqualToString:@"true"] || 
               [stringValue isEqualToString:@"yes"] || 
               [stringValue isEqualToString:@"1"];
    }
    
    return defaultValue;
}

+ (NSInteger)safeIntegerFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key {
    return [self safeIntegerFromDictionary:dictionary forKey:key defaultValue:0];
}

+ (NSInteger)safeIntegerFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key defaultValue:(NSInteger)defaultValue {
    NSNumber *number = [self safeNumberFromDictionary:dictionary forKey:key];
    return number ? [number integerValue] : defaultValue;
}

+ (double)safeDoubleFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key {
    return [self safeDoubleFromDictionary:dictionary forKey:key defaultValue:0.0];
}

+ (double)safeDoubleFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key defaultValue:(double)defaultValue {
    NSNumber *number = [self safeNumberFromDictionary:dictionary forKey:key];
    return number ? [number doubleValue] : defaultValue;
}

#pragma mark - JSON Path Access

+ (id)valueAtPath:(NSString *)path inObject:(id)object {
    if (!path || !object) return nil;
    
    NSArray *components = [path componentsSeparatedByString:@"."];
    id currentObject = object;
    
    for (NSString *component in components) {
        if ([currentObject isKindOfClass:[NSDictionary class]]) {
            currentObject = currentObject[component];
        } else if ([currentObject isKindOfClass:[NSArray class]]) {
            NSInteger index = [component integerValue];
            NSArray *array = (NSArray *)currentObject;
            if (index >= 0 && index < array.count) {
                currentObject = array[index];
            } else {
                return nil;
            }
        } else {
            return nil;
        }
        
        if (!currentObject || [currentObject isKindOfClass:[NSNull class]]) {
            return nil;
        }
    }
    
    return currentObject;
}

+ (BOOL)setValue:(id)value atPath:(NSString *)path inMutableObject:(NSMutableDictionary *)object {
    if (!path || !object) return NO;
    
    NSArray *components = [path componentsSeparatedByString:@"."];
    if (components.count == 0) return NO;
    
    NSMutableDictionary *currentDict = object;
    
    // 导航到目标位置
    for (NSUInteger i = 0; i < components.count - 1; i++) {
        NSString *component = components[i];
        id nextObject = currentDict[component];
        
        if (!nextObject || [nextObject isKindOfClass:[NSNull class]]) {
            // 创建新的字典
            nextObject = [NSMutableDictionary dictionary];
            currentDict[component] = nextObject;
        } else if (![nextObject isKindOfClass:[NSMutableDictionary class]]) {
            // 如果不是可变字典，创建一个新的
            if ([nextObject isKindOfClass:[NSDictionary class]]) {
                nextObject = [nextObject mutableCopy];
                currentDict[component] = nextObject;
            } else {
                return NO; // 无法设置值
            }
        }
        
        currentDict = nextObject;
    }
    
    // 设置最终值
    NSString *finalKey = components.lastObject;
    currentDict[finalKey] = value ?: [NSNull null];
    
    return YES;
}

#pragma mark - JSON Merge

+ (NSDictionary *)mergeDictionary:(NSDictionary *)dict1 withDictionary:(NSDictionary *)dict2 {
    if (!dict1) return dict2;
    if (!dict2) return dict1;
    
    NSMutableDictionary *result = [dict1 mutableCopy];
    
    for (NSString *key in dict2) {
        id value1 = dict1[key];
        id value2 = dict2[key];
        
        if ([value1 isKindOfClass:[NSDictionary class]] && [value2 isKindOfClass:[NSDictionary class]]) {
            // 递归合并字典
            result[key] = [self mergeDictionary:value1 withDictionary:value2];
        } else {
            // 直接覆盖
            result[key] = value2;
        }
    }
    
    return [result copy];
}

#pragma mark - Utility Methods

+ (NSUInteger)jsonDepth:(id)object {
    if (!object || [object isKindOfClass:[NSNull class]]) {
        return 0;
    } else if ([object isKindOfClass:[NSDictionary class]]) {
        NSUInteger maxDepth = 0;
        NSDictionary *dict = (NSDictionary *)object;
        for (id value in dict.allValues) {
            NSUInteger depth = [self jsonDepth:value];
            if (depth > maxDepth) {
                maxDepth = depth;
            }
        }
        return maxDepth + 1;
    } else if ([object isKindOfClass:[NSArray class]]) {
        NSUInteger maxDepth = 0;
        NSArray *array = (NSArray *)object;
        for (id value in array) {
            NSUInteger depth = [self jsonDepth:value];
            if (depth > maxDepth) {
                maxDepth = depth;
            }
        }
        return maxDepth + 1;
    } else {
        return 1; // 基本类型
    }
}

+ (NSUInteger)jsonObjectCount:(id)object {
    if (!object || [object isKindOfClass:[NSNull class]]) {
        return 0;
    } else if ([object isKindOfClass:[NSDictionary class]]) {
        NSUInteger count = 1; // 自身
        NSDictionary *dict = (NSDictionary *)object;
        for (id value in dict.allValues) {
            count += [self jsonObjectCount:value];
        }
        return count;
    } else if ([object isKindOfClass:[NSArray class]]) {
        NSUInteger count = 1; // 自身
        NSArray *array = (NSArray *)object;
        for (id value in array) {
            count += [self jsonObjectCount:value];
        }
        return count;
    } else {
        return 1; // 基本类型
    }
}

+ (NSArray *)allKeysInObject:(id)object {
    NSMutableSet *allKeys = [NSMutableSet set];
    [self collectKeysFromObject:object intoSet:allKeys];
    return [allKeys allObjects];
}

+ (void)collectKeysFromObject:(id)object intoSet:(NSMutableSet *)keySet {
    if ([object isKindOfClass:[NSDictionary class]]) {
        NSDictionary *dict = (NSDictionary *)object;
        [keySet addObjectsFromArray:dict.allKeys];
        for (id value in dict.allValues) {
            [self collectKeysFromObject:value intoSet:keySet];
        }
    } else if ([object isKindOfClass:[NSArray class]]) {
        NSArray *array = (NSArray *)object;
        for (id value in array) {
            [self collectKeysFromObject:value intoSet:keySet];
        }
    }
}

@end